package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.PublishConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.system.domain.PQuestion;
import com.ruoyi.system.domain.bo.PQuestionBo;
import com.ruoyi.system.domain.vo.PQuestionVo;
import com.ruoyi.system.mapper.PQuestionMapper;
import com.ruoyi.system.service.IPQuestionService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 问题Service业务层处理
 *
 * @author ruoyi
 * @date 2022-07-19
 */
@RequiredArgsConstructor
@Service
public class PQuestionServiceImpl implements IPQuestionService {

    private final PQuestionMapper baseMapper;

    private static Logger logger = LoggerFactory.getLogger(PQuestionServiceImpl.class);

    /**
     * 查询问题
     */
    @Override
    public PQuestion queryById(Long id) {
        return baseMapper.selectVoByMyId(id, PublishConstants.QUESTION_TYPE);
    }

    @Override
    public TableDataInfo<PQuestion> queryPageListafter(String search, Long typeId, String userType, String end, PageQuery pageQuery) {
        if (StringUtils.isEmpty(end)) {
            throw new ServiceException("传参错误");
        }

        pageQuery.setPageNum((pageQuery.getPageNum() - 1) * pageQuery.getPageSize());
        List<PQuestion> result = baseMapper.selectMyList(pageQuery, new QueryWrapper<PQuestion>()
            .eq(typeId != null && typeId != 0, "q.type_id", typeId)
            .eq("1".equals(end), "q.is_well", "1")
            .eq("2".equals(end), "q.user_id", LoginHelper.getUserId())
            .eq(!"2".equals(userType), "q.experts_visible", "0")
            .eq("q.del_flag", "0")
            .like(StringUtils.isNotEmpty(search), "q.title", search)
            .orderByDesc("q.create_time"), PublishConstants.QUESTION_TYPE);
        return TableDataInfo.build(result);
    }

    /**
     * 查询问题列表
     */
    @Override
    public TableDataInfo<PQuestion> queryPageList(PQuestion bo, PageQuery pageQuery) {
        QueryWrapper<PQuestion> lqw = buildMyQueryWrapper(bo);
        pageQuery.setPageNum((pageQuery.getPageNum() - 1) * pageQuery.getPageSize());
        List<PQuestion> result = baseMapper.selectMyList(pageQuery, lqw, PublishConstants.QUESTION_TYPE);
        return TableDataInfo.build(result);
    }

    /**
     * 自定义查询构造器
     */
    private QueryWrapper<PQuestion> buildMyQueryWrapper(PQuestion bo) {
        QueryWrapper<PQuestion> wrapper = Wrappers.query();
        wrapper.like(StringUtils.isNotBlank(bo.getUserName()), "u.user_name", bo.getUserName())
            .eq(ObjectUtil.isNotNull(bo.getTypeId()), "q.type_id", bo.getTypeId())
            .eq(StringUtils.isNotBlank(bo.getCheckFlag()), "q.check_flag", bo.getCheckFlag());
        return wrapper;
    }

    /**
     * 查询问题列表
     */
    @Override
    public List<PQuestionVo> queryList(PQuestionBo bo) {
        LambdaQueryWrapper<PQuestion> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PQuestion> buildQueryWrapper(PQuestionBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PQuestion> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), PQuestion::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getMsg()), PQuestion::getMsg, bo.getMsg());
        lqw.eq(bo.getTypeId() != null, PQuestion::getTypeId, bo.getTypeId());
        lqw.eq(bo.getUserId() != null, PQuestion::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getCheckFlag()), PQuestion::getCheckFlag, bo.getCheckFlag());
        lqw.eq(bo.getReadNum() != null, PQuestion::getReadNum, bo.getReadNum());
        lqw.eq(bo.getAskNum() != null, PQuestion::getAskNum, bo.getAskNum());
        return lqw;
    }

    /**
     * 新增问题
     */
    @Override
    public Boolean insertByBo(PQuestionBo bo) {
        PQuestion add = BeanUtil.toBean(bo, PQuestion.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改问题
     */
    @Override
    public Boolean updateByBo(PQuestionBo bo) {
        PQuestion update = BeanUtil.toBean(bo, PQuestion.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PQuestion entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除问题
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean insertByUserBo(PQuestionBo bo) {
        PQuestion add = BeanUtil.toBean(bo, PQuestion.class);
        Long userId = LoginHelper.getUserId();
        add.setUserId(userId);
        add.setCheckFlag(PublishConstants.COMMON_NO);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PQuestion queryClickById(Long id) {
        // 获取锁成功，处理业务
        PQuestion pQuestion = baseMapper.selectVoByMyId(id, PublishConstants.QUESTION_TYPE);
        if (ObjectUtil.isEmpty(pQuestion)) {
            throw new ServiceException("非法数据！");
        }

        Long userId = LoginHelper.getUserId();
        String readKey = PublishConstants.QUESTION_READ_KEY + userId;

        // 设置每个用户一天只浏览一次
        if (!RedisUtils.hasKey(readKey)) {
            RedisUtils.setCacheObject(readKey, 1, Duration.ofDays(1));
            // 更新阅读量
            Long readNum = pQuestion.getReadNum();
            pQuestion.setReadNum(++readNum);
            baseMapper.updateById(pQuestion);
            return pQuestion;
        }

        return pQuestion;
    }

    @Override
    public void updateReadNum(Long questionId) {
        PQuestion pq = this.baseMapper.selectOne(new LambdaQueryWrapper<PQuestion>().eq(PQuestion::getId, questionId));
        this.baseMapper.update(null, new LambdaUpdateWrapper<PQuestion>().set(PQuestion::getReadNum, pq.getReadNum() + 1).eq(PQuestion::getId, pq.getId()));
    }
}
